package main

import (
	"fmt"
	"io"
	"os"
)

/**
Deferred 函数
在一个自定义函数中，你打开了一个文件，然后需要关闭它以释放资源。不管你的代码执行了多少分支，是否出现了错误，文件是一定要关闭的，这样才能保证资源的释放。
如果这个事情由开发人员来做，随着业务逻辑的复杂会变得非常麻烦，而且还有可能会忘记关闭。
基于这种情况，Go 语言为我们提供了 defer 函数，可以保证文件关闭后一定会被执行，不管你自定义的函数出现异常还是错误。
下面的代码是 Go 语言标准包 ioutil 中的 ReadFile 函数，它需要打开一个文件，然后通过 defer 关键字确保在 ReadFile 函数执行结束后，f.Close() 方法被执行，这样文件的资源才一定会释放。
*/

func readFile(filename string) ([]byte, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	// defer 关键字用于修饰一个函数或者方法，使得该函数或者方法在返回前才会执行，也就说被延迟，但又可以保证一定会执行。
	defer f.Close()
	return io.ReadAll(f)
}

/**
以上函数执行顺序
1.先执行ReadAll()
2.再执行defer
3.最后执行Return
*/

func testDefer() (n int, err error) {
	/**
	如果有多个defer的时候，是按照栈的顺序，先近后出依次执行的。
	1
	ok
	4
	3
	2
	*/
	fmt.Println("1")
	defer fmt.Println("2")
	defer fmt.Println("3")
	defer fmt.Println("4")
	return fmt.Println("ok")
}

//func main() {
//	testDefer()
//}
